package day0803API.WebServer;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class HttpServletResponse {
    Socket socket;


    //状态行的信息：
    private  int statusCode=200;
    //通信正常用200， 服务器有问题5XX表示， 客户端有问题用4XX表示(如果浏览器访问的资源本次情趣无法处理，需要浏览器发第二次请求302状态表示)
    //如果客户端访问的资源本次情趣无法处理，需要客户端发第二次请求，则服务端会给客户端302状态码，浏览器会自动发送第二次请求。 (重定向)
    private  String statusReason="OK";
    //状态行的协议版本全部是 Http1.1

    //响应正文
    private  File contentFile;


    //ClientThread:run()    new HttpServletResponse(socket)
    //将run()方法中传入socket对象存入到成员变量中
    public HttpServletResponse(Socket socket) {
        this.socket = socket;
    }

    public File getContentFile() {
        return contentFile;
    }

    public void setContentFile(File contentFile) {
        this.contentFile = contentFile;
    }

    //用Socket的输出流将File contentFile写出到客户端
    public void responseDataToClient(){
        //A.将响应行的信息用输出流写出到客户端
        responseStatusLine();//response返回status状态Line行
        //B.将响应头的信息用输出流写出到客户端
        responseHeaders();
        //C.将响应正文的信息用输出流写出到客户端
        responseContent();
    }


    //response返回status状态Line行

    /**
     * A.将响应行的信息用输出流写出到客户端
     */
    private void responseStatusLine() {
        String line="HTTP/1.1 "+statusCode+" "+statusReason;
        sendLineToClient(line);//用sendLineToClient方法给客户端返回一行文字
    }

    /**
     * B.将响应头的信息用输出流写出到客户端
     */
    private void responseHeaders() {
        //调用sendLineToClient方法三次，发送三个响应头
        //返回一个表示响应正文的格式的响应头
        //此响应头的具体含义：  给浏览器返回的响应正文的格式是text/html(网页文本信息)
        sendLineToClient("Content-Type: text/html");  //text文本/ html网页    网页文本信息
        //返回一个表示响应正文的长度的响应头
        sendLineToClient("Content-Length: "+contentFile.length());
        //返回一个空行
        sendLineToClient("");
    }


    /**
     * C.将响应正文的信息用输出流写出到客户端
     */
    private void responseContent() {
        try (//1.用FileInputStream文件输入流读取网页文件
             FileInputStream fis=new FileInputStream(contentFile)){
            //2.用socket获取字节输出流(让字节 输出流os自动关闭)(用字节 输出路OutputStream写出网页文件数据<到客户端>)
            OutputStream os=socket.getOutputStream();//返回给浏览器的不是文件(返回的是网页文件里的代码)
            byte[]  data=new byte[1024*5];// 5M
            int length=-1;
            while( (length=fis.read(data)) != -1  ){//fis.read(data)用文件输入流 FileInputStream fis读取网页文件中的字节数据到data数组中
                os.write(data, 0, length);//用socket获取字节输出流os，将读取到的字节数组data数据写出到客户端(从数组第0位开始，写出length个)
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }




    //用sendLineToClient方法给客户端返回一行文字

    /**
     * 用Socket中的输出流将一行文字信息line写出到客户端
     * @param line
     */
    private void sendLineToClient(String line) {
        try {//1.用socket获取字节输出流
            OutputStream os=socket.getOutputStream();
            //2.将一行文字信息line转化为字节数组//服务端的ServerSocket接收文字数据默认会采用ISO_8859_1
            //我们用代码给客户端返回数据也采用ISO_8859_1编码(服务端接受和发送都采用ISO_8859_1)
            byte[] bytes=line.getBytes(StandardCharsets.ISO_8859_1);
            //3.用输出流的write方法一次性将line转化成的字节数组全部写出到客户端
            os.write(bytes);
            //4.在本行文字性信息写出到客户端的末尾再写出一个回车符13 和换行符10
            os.write(13);
            os.write(10);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
